﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace WFL.Wrapper.Highcharts
{
    public class JsonObject
    {

        protected Dictionary<string, object> Pairs = new Dictionary<string, object>();

        public virtual string Name
        {
            get
            {
                string name = this.GetType().Name;
                name = Regex.Replace(name, @"^([A-Z])(.*?)Object$", delegate(Match match)
                {
                    return match.Groups[1].Value.ToLower() + match.Groups[2].Value;
                });
                return name;
            }
        }

        public object this[string name]
        {
            get
            {
                if (!Pairs.ContainsKey(name))
                {
                    return null;
                }
                return Pairs[name];
            }
            set
            {
                Pairs[name] = value;
            }
        }

        public void Set(JsonObject obj)
        {
            Pairs[obj.Name] = obj;
        }

        public T GetValue<T>(string name)
        {
            object value = null;
            if (Pairs.ContainsKey(name))
            {
                value = Pairs[name];
            }
            return value != null ? (T)value : default(T);
        }

        public bool Remove(string name)
        {
            return Pairs.Remove(name);
        }

        public void Clear()
        {
            Pairs.Clear();
        }

        public void Write(TextWriter writer)
        {
            writer.Write('{');
            if (Pairs.Count > 0)
            {
                int index = 0;
                foreach (KeyValuePair<string, object> pair in Pairs)
                {
                    if (index++ > 0)
                    {
                        writer.Write(',');
                    }
                    writer.Write(pair.Key);
                    writer.Write(':');
                    WriteValue(writer, pair.Value);
                }
            }
            writer.Write('}');
        }

        private void WriteValue(TextWriter writer, object value)
        {
            if (value == null)
            {
                writer.Write("null");
            }
            else if (value is string)
            {
                writer.Write('\'');
                writer.Write(((string)value).Replace('\'', '"'));
                writer.Write('\'');
            }
            else if (value is JsonObject)
            {
                ((JsonObject)value).Write(writer);
            }
            else if (value is bool)
            {
                writer.Write(((bool)value) ? "true" : "false");
            }
            else if (value is Array)
            {
                Array array = (Array)value;
                if (array.Length > 0)
                {
                    //各维度下限、上限
                    int[,] ranks = new int[array.Rank, 2];
                    //各维度当前位置索引
                    int[] rankIndex = new int[array.Rank];
                    for (int i = 0; i < array.Rank; i++)
                    {
                        ranks[i, 0] = array.GetLowerBound(i);
                        ranks[i, 1] = array.GetUpperBound(i);
                    }

                    for (int i = 0; i < array.Length; i++)
                    {
                        if (i > 0)
                        {
                            writer.Write(',');
                        }
                        for (int r = array.Rank - 1; r >= 0; r--)
                        {
                            if (rankIndex[r] == 0)
                            {
                                //第一个元素
                                writer.Write('[');
                            }
                            else
                            {
                                break;
                            }
                        }
                        WriteValue(writer, array.GetValue(rankIndex));
                        //更新各个维度位置
                        //上个维度位置超过上限被重置
                        bool lastRankIndexReset = false;
                        for (int r = array.Rank - 1; r >= 0; r--)
                        {
                            if (r != array.Rank - 1 && !lastRankIndexReset)
                            {
                                break;
                            }
                            if (rankIndex[r] == ranks[r, 1])
                            {
                                //达到维度上限
                                rankIndex[r] = 0;
                                lastRankIndexReset = true;
                            }
                            else
                            {
                                rankIndex[r]++;
                                lastRankIndexReset = false;
                            }
                        }
                        for (int r = array.Rank - 1; r >= 0; r--)
                        {
                            if (rankIndex[r] == 0)
                            {
                                //第一个元素
                                writer.Write(']');
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }
            }
            else
            {
                writer.Write(value.ToString());
            }
        }

        public override string ToString()
        {
            StringBuilder jsonString = new StringBuilder();
            StringWriter writer = new StringWriter(jsonString);
            try
            {
                Write(writer);
                writer.Flush();
                return jsonString.ToString();
            }
            finally
            {
                writer.Close();
            }
        }
    }
}
